import datetime,math
from jili.price.ta import creat_ta_calcor as ta_frame
from mohe.core.obj import obj_trade
from jili.data.db import tradecal
from copy import deepcopy
from jili.core.printlog import print
#---------------k线字段
#open,high,low,close,volume
#vwap:均价，pos:剩余仓位，updatetime
#使用dict；考虑场景：
def copydict(t):
    r={}
    for k,v in t.items():
        r[k]=v
    return r
class kline1d:
    def __init__(self,obj="",isnight=True,bars_len=2):
        from jili.data.db import tradecal
        self.isnight=isnight
        self.obj=obj
        self.bar={}
        self.bars=[]
        self.tradecal=tradecal
        self.lasttimekey=None
        self.bars_len=bars_len
        self.tas = []
        self.onbarcall=[]
        self.ondata=self.onbar
    def setonbar(self,call):
        self.onbarcall.append(call)
    def add_ta(self, ta_arg):
        ta0 = ta_frame(ta_arg)
        self.tas.append(ta0)
    def __calc_ta(self,bar):
        for i in self.tas:
            r = i.onbar(bar)
            bar.update(r)
    def gethisbars(self,date=None,num=60):
        if date is None:
            date0=datetime.datetime.now()
        elif isinstance(date,str):
            from jili.core.convert import str2datetime
            date0=str2datetime(date)
        else:
            date0=date
    def ontick(self,t):
        if "obj" in t.keys():
            self.obj=t["obj"]
        timekey=t["timekey"]
        if self.bars:
            bar0=self.bars[-1]
            bartimekey=self.gettimekey(timekey)
            if bartimekey == bar0["timekey"]:
                if "OpenPrice" in t.keys():
                    if bar0["high"] != t["HighestPrice"]:
                        bar0["high"] = t["HighestPrice"]
                        bar0["hightime"] = timekey
                    elif bar0["low"] != t["LowestPrice"]:
                        bar0["low"] = t["LowestPrice"]
                        bar0["lowtime"] = timekey
                else:
                    if bar0["high"] < t["LastPrice"]:
                        bar0["high"] = t["LastPrice"]
                        bar0["hightime"] = timekey
                    elif bar0["low"] > t["LastPrice"]:
                        bar0["low"] = t["LastPrice"]
                        bar0["lowtime"] = timekey
                bar0["close"] = t["LastPrice"]
                bar0["volume"] = t["Volume"]
                if "AveragePrice" in t.keys():
                    bar0["vwap"] = t["AveragePrice"]
                else:
                    bar0["vwap"] = 0
                bar0["pos"]=t["OpenInterest"]
                bar0["uptime"] = timekey
                self.__calc_ta(bar0)
            else:
                bar0 = {}
                bar0["timekey"] = bartimekey
                bar0["obj"] = t["obj"]
                if "OpenPrice" in t.keys():
                    bar0["open"] = t["OpenPrice"]
                    bar0["high"] = t["HighestPrice"]
                    bar0["low"] = t["LowestPrice"]
                else:
                    bar0["open"] = t["LastPrice"]
                    bar0["high"] = t["LastPrice"]
                    bar0["low"] = t["LastPrice"]
                bar0["close"] = t["LastPrice"]
                bar0["volume"] = t["Volume"]
                if "AveragePrice" in t.keys():
                    bar0["vwap"] = t["AveragePrice"]
                else:
                    bar0["vwap"] = 0
                bar0["pos"] = t["OpenInterest"]
                bar0["uptime"] = timekey
                bar0["hightime"] = timekey
                bar0["lowtime"] = timekey
                bar0["opentime"] = timekey
                self.__calc_ta(bar0)
                self.bars.append(bar0)
                self.calldayend(timekey,bar0)
                if len(self.bars)>self.bars_len:
                    self.bars.pop(0)
                self.bar = bar0
        else:
            bar0={}
            bar0["timekey"] = self.gettimekey(timekey)
            bar0["obj"] = t["obj"]
            if "OpenPrice" in t.keys():
                bar0["open"] = t["OpenPrice"]
                bar0["high"] = t["HighestPrice"]
                bar0["low"] = t["LowestPrice"]
            else:
                bar0["open"] = t["LastPrice"]
                bar0["high"] = t["LastPrice"]
                bar0["low"] = t["LastPrice"]
            bar0["close"] = t["LastPrice"]
            bar0["volume"] = t["Volume"]
            if "AveragePrice" in t.keys():
                bar0["vwap"] = t["AveragePrice"]
            else:
                bar0["vwap"] = 0
            bar0["pos"]=t["OpenInterest"]
            bar0["uptime"] = timekey
            bar0["hightime"] = timekey
            bar0["lowtime"] = timekey
            bar0["opentime"] = timekey
            self.__calc_ta(bar0)
            self.bars.append(bar0)
            self.calldayend(timekey, bar0)
            self.bar=bar0
        return bar0
    def calldayend(self,timekey,bar0):
        if timekey.hour>=14 and timekey.hour<=15 and timekey.second>=59:
            for i in self.onbarcall:
                i(bar0)
        else:
            return False
    def gettimekey(self,a):
        hour = a.hour
        if hour >= 20:
            return self.tradecal.getnexttradeday(a)
        else:
            return datetime.datetime(a.year, a.month, a.day)
    def onbar(self,b):
        if "obj" in b.keys():
            self.obj=b["obj"]
        timekey = self.gettimekey(b["uptime"])
        if self.bars:
            bar0=self.bars[-1]
            if timekey == bar0["timekey"]:
                if bar0["high"] < b["high"]:
                    bar0["high"] = b["high"]
                    bar0["hightime"] = b["hightime"]
                elif bar0["low"] > b["low"]:
                    bar0["low"] =b["low"]
                    bar0["lowtime"] = b["lowtime"]
                bar0["close"] = b["close"]
                bar0["volume"] = bar0["volume"]+b["volume"]
                bar0["vwap"] = b["vwap"]
                bar0["pos"]=b["pos"]
                bar0["uptime"] = b["uptime"]
                self.__calc_ta(bar0)
            else:
                bar0 = copydict(b)
                bar0["timekey"] = timekey
                self.__calc_ta(bar0)
                self.bars.append(bar0)
                self.calldayend(b["uptime"], bar0)
                if len(self.bars)>self.bars_len:
                    self.bars.pop(0)
                self.bar = bar0
        else:
            bar0=copydict(b)
            bar0["timekey"] = timekey
            self.__calc_ta(bar0)
            self.bars.append(bar0)
            self.calldayend(b["uptime"], bar0)
            self.bar=bar0
        return bar0
class kline1m:
    def __init__(self,obj,bars_len=2,ktype="1110",preclose=None):
        self.oncallkey=None
        self.obj=obj
        self.iscall=True
        self.bars_len=bars_len
        self.pretimekey=None
        self.endtimes = []
        self.trade_time=obj_trade(obj)
        self.bar={}
        self.bars = []
        self.onbarcall = []
        self.tas=[]
        self.ktype=ktype
        self.preclose=preclose
        self.isstartday=True
        self.ondata=self.ontick
        """:cvar
        0位:是否过滤无成交数据量：1：过滤，0：不过滤
        1位：k触发回调规则：0：滞后触发，1.提前触发，2.实时触发
        2位：是否补齐k线；1：补齐，0：不补
        3位：是否整点tick共用k线，1：是，0：否
        1110：
        1100
        0110
        0100
        0011
        0001
        """
    def add_ta(self,ta_arg):
        ta0=ta_frame(ta_arg)
        self.tas.append(ta0)
    def __calc_ta(self,bar):
        #print(bar)
        for i in self.tas:
            r = i.onbar(bar)
            #print(r)
            bar.update(r)
        return bar
    def reset(self):
        self.bar={}
        self.bars = []
    def setonbar(self,call):
        self.onbarcall.append(call)

    def ontick(self,t):
        if "obj" in t.keys():
            self.obj=t["obj"]
        """

        Args:
            t: ["timekey","LastPrice","volume","AveragePrice","OpenInterest"]

        Returns:

        """
        #print("kline1m",t)
        timekey0=t["timekey"]
        vv="Volume"
        if self.ktype[0]=="1":
            vv="volume"
        if t[vv] == 0:
            return {}
        if self.checktime(timekey0):
            timekey=self.getbartimekey(timekey0)
            if self.bars:
                bar=self.bars[-1]
                if timekey==bar["timekey"]:
                    if bar["high"]<t["LastPrice"]:
                        bar["high"] = t["LastPrice"]
                        bar["hightime"] = timekey0
                    elif bar["low"] > t["LastPrice"]:
                        bar["low"] = t["LastPrice"]
                        bar["lowtime"] = timekey0
                    bar["close"]=t["LastPrice"]
                    bar["volume"]=bar["volume"]+t["volume"]
                    if "AveragePrice" in t.keys():
                        bar["vwap"]=t["AveragePrice"]
                    else:
                        bar["vwap"] =0
                    bar["pos"]=t["OpenInterest"]
                    bar["uptime"]=timekey0
                    if self.ktype[1] == "1":
                        if timekey0.second >= 59:
                            if self.iscall:
                                self.__calc_ta(bar)
                                if self.onbarcall:
                                    for i in self.onbarcall:
                                        i(self.bar)
                                self.iscall = False
                        else:
                            self.iscall = True
                    elif self.ktype[1] == "2":
                        if self.onbarcall:
                            self.__calc_ta(bar)
                            for i in self.onbarcall:
                                i(self.bar)
                else:
                    if self.iscall and self.ktype[1] == "1":
                        self.__calc_ta(bar)
                        if self.onbarcall:
                            for i in self.onbarcall:
                                i(bar)
                    if self.ktype[3]=="1":
                        if timekey0 == timekey:
                            if bar["high"] < t["LastPrice"]:
                                bar["high"] = t["LastPrice"]
                                bar["hightime"] = timekey0
                            elif bar["low"] > t["LastPrice"]:
                                bar["low"] = t["LastPrice"]
                                bar["lowtime"] = timekey0
                            bar["close"] = t["LastPrice"]
                            bar["volume"] = bar["volume"] + t["volume"]
                            if "AveragePrice" in t.keys():
                                bar["vwap"] = t["AveragePrice"]
                            else:
                                bar["vwap"] = 0
                            bar["pos"] = t["OpenInterest"]
                            bar["uptime"] = timekey0
                            if self.ktype[1] != "1":
                                self.__calc_ta(bar)
                                if self.onbarcall:
                                    for i in self.onbarcall:
                                        i(bar)
                            bar0 = {}
                            bar0["timekey"] = timekey
                            bar0["obj"] = self.obj
                            bar0["open"] = t["LastPrice"]
                            bar0["high"] = t["LastPrice"]
                            bar0["low"] = t["LastPrice"]
                            bar0["close"] = t["LastPrice"]
                            bar0["volume"] = 0
                            if "AveragePrice" in t.keys():
                                bar0["vwap"] = t["AveragePrice"]
                            else:
                                bar0["vwap"] = 0
                            bar0["pos"] = t["OpenInterest"]
                            bar0["uptime"] = timekey0
                            bar0["hightime"] = timekey0
                            bar0["lowtime"] = timekey0
                            bar0["opentime"] = timekey0
                            self.bars.append(bar0)
                            if len(self.bars) > self.bars_len:
                                self.bars.pop(0)
                            self.bar = bar0
                        else:
                            if self.ktype[1] != "1":
                                self.__calc_ta(self.bar)
                                if self.onbarcall:
                                    for i in self.onbarcall:
                                        i(self.bar)
                            bar0 = {}
                            bar0["timekey"] = timekey
                            bar0["obj"] = self.obj
                            bar0["open"] = t["LastPrice"]
                            bar0["high"] = t["LastPrice"]
                            bar0["low"] = t["LastPrice"]
                            bar0["close"] = t["LastPrice"]
                            bar0["volume"] = t["volume"]
                            if "AveragePrice" in t.keys():
                                bar0["vwap"] = t["AveragePrice"]
                            else:
                                bar0["vwap"] = 0
                            bar0["pos"] = t["OpenInterest"]
                            bar0["uptime"] = timekey0
                            bar0["hightime"] = timekey0
                            bar0["lowtime"] = timekey0
                            bar0["opentime"] = timekey0
                            self.bars.append(bar0)
                            if len(self.bars) > self.bars_len:
                                self.bars.pop(0)
                            self.bar = bar0
                        if self.ktype[1] == "2":
                            self.__calc_ta(bar0)
                            if self.onbarcall:
                                for i in self.onbarcall:
                                    i(self.bar)
                    else:
                        bar0={}
                        bar0["timekey"]=timekey
                        bar0["obj"]=self.obj
                        bar0["open"]=t["LastPrice"]
                        bar0["high"]=t["LastPrice"]
                        bar0["low"]=t["LastPrice"]
                        bar0["close"]=t["LastPrice"]
                        bar0["volume"]=t["volume"]
                        if "AveragePrice" in t.keys():
                            bar0["vwap"] = t["AveragePrice"]
                        else:
                            bar0["vwap"] = 0
                        bar0["pos"]=t["OpenInterest"]
                        bar0["uptime"]=timekey0
                        bar0["hightime"] = timekey0
                        bar0["lowtime"] = timekey0
                        bar0["opentime"] = timekey0
                        self.bars.append(bar0)
                        if len(self.bars)>self.bars_len:
                            self.bars.pop(0)
                        self.bar=bar0
                        if self.ktype[1] == "2":
                            self.__calc_ta(bar0)
                            if self.onbarcall:
                                for i in self.onbarcall:
                                    i(self.bar)
                    self.iscall = True
            else:
                bar0={}
                bar0["timekey"]=timekey
                bar0["obj"]=self.obj
                bar0["open"]=t["LastPrice"]
                bar0["high"]=t["LastPrice"]
                bar0["low"]=t["LastPrice"]
                bar0["close"]=t["LastPrice"]
                bar0["volume"]=t["volume"]
                if "AveragePrice" in t.keys():
                    bar0["vwap"] = t["AveragePrice"]
                else:
                    bar0["vwap"] = 0
                bar0["pos"]=t["OpenInterest"]
                bar0["uptime"]=timekey0
                bar0["hightime"] = timekey0
                bar0["lowtime"] = timekey0
                bar0["opentime"] = timekey0
                self.bars.append(bar0)
                self.bar=bar0
                if self.ktype[1] == "2":
                    self.__calc_ta(bar0)
                    if self.onbarcall:
                        for i in self.onbarcall:
                            i(self.bar)
                self.iscall = True
            self.pretimekey=timekey
        return self.bar
    def getnexttimekey(self,a):
        t = a + datetime.timedelta(minutes=1)
        end0 = self.trade_time.getend_datetime(a)
        if t in end0:
            n=0
            for i in end0:
                n=n+1
                if t==i:
                    break
            stop0=self.trade_time.getstop_datetime(a)
            t=stop0[n][1]
        return t

    def genkline(self,a,b,close):
        if close is None:
            return None
        if self.isstartday:
            t=a
        else:
            t = self.getnexttimekey(a)
        while t<b:
            if self.trade_time.istradetime(t):
                if self.isstartday:
                    bar0 = {}
                    bar0["timekey"] = t
                    bar0["obj"] = self.obj
                    bar0["open"] = close
                    bar0["high"] = close
                    bar0["low"] = close
                    bar0["close"] = close
                    bar0["volume"] = 0
                    bar0["vwap"] = 0
                    bar0["pos"] = 0
                    bar0["uptime"] = t
                    bar0["hightime"] = t
                    bar0["lowtime"] = t
                    bar0["opentime"] = t
                else:
                    bar0 = deepcopy(self.bars[-1])
                    bar0["timekey"] = t
                    bar0["volume"] = 0
                    bar0["uptime"] = t
                    bar0["open"] = bar0["close"]
                    bar0["high"] = bar0["close"]
                    bar0["low"] = bar0["close"]
                    bar0["uptime"] = t
                    bar0["hightime"] = t
                    bar0["lowtime"] = t
                    bar0["opentime"] = t
                self.bars.append(bar0)
                if len(self.bars) > self.bars_len:
                    self.bars.pop(0)
                self.bar=bar0
                self.__calc_ta(bar0)
                if self.onbarcall:
                    for i in self.onbarcall:
                        i(self.bar)
            t=self.getnexttimekey(t)
        self.isstartday = False
    def check_genendbar(self):
        t = self.bar["timekey"]
        end0 = self.trade_time.getend_datetime(t)
        b=end0[-1]
        if t + datetime.timedelta(minutes=1) < b:
            self.genkline(t, b, self.bar["close"])
    def getbartimekey(self,a):
        b = datetime.datetime(a.year, a.month, a.day, a.hour, a.minute)
        end0=self.trade_time.getend_datetime(a)
        if b in end0:
            b = b-datetime.timedelta(minutes=1)
        if self.ktype[2]=="1":
            if self.isstartday:
                t=self.trade_time.gettrade_datetime(a)
                t=t[0][0]
                if t!=b:
                    self.genkline(t,b,self.preclose)
                self.isstartday = False
            else:
                t=self.bar["timekey"]
                if t+datetime.timedelta(minutes=1)<b:
                    self.genkline(t,b,self.bar["close"])
        return b
    def checktime(self,a):
        return self.trade_time.istradetime(a)
class kline1m_kq:
    def __init__(self,obj,bars_len=2,preclose=None):
        self.obj=obj
        self.iscall=True
        self.bars_len=bars_len
        self.pretimekey=None
        self.endtimes = []
        self.trade_time = obj_trade(obj)
        self.bar={}
        self.bars = []
        self.onbarcall = []
        self.tas=[]
        self.preclose = preclose
        self.isstartday = True
        self.ondata=self.ontick
        """:cvar
        ktype:补不补K；是否按时间提前更新k线，滞后更新k;
        """
    def add_ta(self,ta_arg):
        ta0=ta_frame(ta_arg)
        self.tas.append(ta0)
    def __calc_ta(self,bar):
        #print(bar)
        for i in self.tas:
            r = i.onbar(bar)
            #print(r)
            bar.update(r)
        return bar
    def reset(self):
        self.bar={}
        self.bars = []
    def setonbar(self,call):
        self.onbarcall.append(call)
    def ontick(self,t):
        if "obj" in t.keys():
            self.obj=t["obj"]
        """

        Args:
            t: ["timekey","LastPrice","volume","AveragePrice","OpenInterest"]

        Returns:

        """
        #print("kline1m",t)
        timekey0=t["timekey"]
        if t["Volume"]==0:
            return {}
        if self.checktime(timekey0):
            timekey=self.getbartimekey(timekey0)
            # if t["volume"]==0:
            #     print("tick",t)
            if self.bars:
                bar=self.bars[-1]
                if timekey==bar["timekey"]:
                    if bar["high"]<t["LastPrice"]:
                        bar["high"] = t["LastPrice"]
                        bar["hightime"] = timekey0
                    elif bar["low"] > t["LastPrice"]:
                        bar["low"] = t["LastPrice"]
                        bar["lowtime"] = timekey0
                    bar["close"]=t["LastPrice"]
                    bar["volume"]=bar["volume"]+t["volume"]
                    if "AveragePrice" in t.keys():
                        bar["vwap"]=t["AveragePrice"]
                    else:
                        bar["vwap"] =0
                    bar["pos"]=t["OpenInterest"]
                    bar["uptime"]=timekey0
                    # if timekey0.second >= 59:
                    #     if self.iscall and self.onbarcall:
                    #         self.__calc_ta(bar)
                    #         for i in self.onbarcall:
                    #             i(self.bar)
                    #         self.iscall = False
                    # else:
                    #     self.iscall = True
                else:
                    if timekey0==timekey:
                        if bar["high"]<t["LastPrice"]:
                            bar["high"] = t["LastPrice"]
                            bar["hightime"] = timekey0
                        elif bar["low"] > t["LastPrice"]:
                            bar["low"] = t["LastPrice"]
                            bar["lowtime"] = timekey0
                        bar["close"]=t["LastPrice"]
                        bar["volume"]=bar["volume"]+t["volume"]
                        if "AveragePrice" in t.keys():
                            bar["vwap"]=t["AveragePrice"]
                        else:
                            bar["vwap"] =0
                        bar["pos"]=t["OpenInterest"]
                        bar["uptime"]=timekey0
                        if self.onbarcall:
                            self.__calc_ta(bar)
                            for i in self.onbarcall:
                                i(bar)
                        bar0={}
                        bar0["timekey"]=timekey
                        bar0["obj"]=self.obj
                        bar0["open"]=t["LastPrice"]
                        bar0["high"]=t["LastPrice"]
                        bar0["low"]=t["LastPrice"]
                        bar0["close"]=t["LastPrice"]
                        bar0["volume"]=0
                        if "AveragePrice" in t.keys():
                            bar0["vwap"] = t["AveragePrice"]
                        else:
                            bar0["vwap"] = 0
                        bar0["pos"]=t["OpenInterest"]
                        bar0["uptime"]=timekey0
                        bar0["hightime"] = timekey0
                        bar0["lowtime"] = timekey0
                        bar0["opentime"] = timekey0
                    else:
                        if self.onbarcall:
                            self.__calc_ta(self.bar)
                            for i in self.onbarcall:
                                i(self.bar)
                        bar0 = {}
                        bar0["timekey"] = timekey
                        bar0["obj"] = self.obj
                        bar0["open"] = t["LastPrice"]
                        bar0["high"] = t["LastPrice"]
                        bar0["low"] = t["LastPrice"]
                        bar0["close"] = t["LastPrice"]
                        bar0["volume"] = t["volume"]
                        if "AveragePrice" in t.keys():
                            bar0["vwap"] = t["AveragePrice"]
                        else:
                            bar0["vwap"] = 0
                        bar0["pos"] = t["OpenInterest"]
                        bar0["uptime"] = timekey0
                        bar0["hightime"] = timekey0
                        bar0["lowtime"] = timekey0
                        bar0["opentime"] = timekey0
                    # self.__calc_ta(bar0)
                    self.bars.append(bar0)
                    if len(self.bars)>self.bars_len:
                        self.bars.pop(0)
                    self.bar=bar0
                    # if self.iscall and self.onbarcall:
                    #     for i in self.onbarcall:
                    #         i(self.bar)
                    #     self.iscall = False
            else:
                bar0={}
                bar0["timekey"]=timekey
                bar0["obj"]=self.obj
                bar0["open"]=t["LastPrice"]
                bar0["high"]=t["LastPrice"]
                bar0["low"]=t["LastPrice"]
                bar0["close"]=t["LastPrice"]
                bar0["volume"]=t["volume"]
                if "AveragePrice" in t.keys():
                    bar0["vwap"] = t["AveragePrice"]
                else:
                    bar0["vwap"] = 0
                bar0["pos"]=t["OpenInterest"]
                bar0["uptime"]=timekey0
                bar0["hightime"] = timekey0
                bar0["lowtime"] = timekey0
                bar0["opentime"] = timekey0
                # self.__calc_ta(bar0)
                self.bars.append(bar0)
                self.bar=bar0
                # if self.iscall and self.onbarcall:
                #     for i in self.onbarcall:
                #         i(self.bar)
                #     self.iscall = False
            self.pretimekey=timekey
        return self.bar
    def getnexttimekey(self,a,):
        t = a + datetime.timedelta(minutes=1)
        end0 = self.trade_time.getend_datetime(a)
        if t in end0:
            n = 0
            for i in end0:
                n = n + 1
                if t == i:
                    break
            stop0 = self.trade_time.getstop_datetime(a)
            t = stop0[n][1]
        return t

    def genkline(self, a, b, close):
        t = self.getnexttimekey(a)
        while t < b:
            if self.trade_time.istradetime(t):
                if self.isstartday:
                    bar0 = {}
                    bar0["timekey"] = t
                    bar0["obj"] = self.obj
                    bar0["open"] = close
                    bar0["high"] = close
                    bar0["low"] = close
                    bar0["close"] = close
                    bar0["volume"] = 0
                    bar0["vwap"] = 0
                    bar0["pos"] = 0
                    bar0["uptime"] = t
                    bar0["hightime"] = t
                    bar0["lowtime"] = t
                    bar0["opentime"] = t
                    self.isstartday = False
                else:
                    bar0 = deepcopy(self.bars[-1])
                    bar0["timekey"] = t
                    bar0["volume"] = 0
                    bar0["uptime"] = t
                    bar0["open"] = bar0["close"]
                    bar0["high"] = bar0["close"]
                    bar0["low"] = bar0["close"]
                self.bars.append(bar0)
                if len(self.bars) > self.bars_len:
                    self.bars.pop(0)
                self.bar = bar0
                self.__calc_ta(bar0)
                if self.onbarcall:
                    for i in self.onbarcall:
                        i(self.bar)
            t = self.getnexttimekey(t)

    def getbartimekey(self, a):
        b = datetime.datetime(a.year, a.month, a.day, a.hour, a.minute)
        end0 = self.trade_time.getend_datetime(a)
        if b in end0:
            b = b - datetime.timedelta(minutes=1)
        if self.ktype[2] == "1":
            if self.isstartday:
                t = self.trade_time.gettrade_datetime(a)
                t = t[0][0]
                if t + datetime.timedelta(minutes=1) < b:
                    self.genkline(t, b, self.preclose)
            else:
                t = self.bar["timekey"]
                if t + datetime.timedelta(minutes=1) < b:
                    self.genkline(t, b, self.bar["close"])
        return b
    def checktime(self,a):
        return self.trade_time.istradetime(a)
def subtime_minute(t1,t0):
    return (t1.hour-t0.hour)*60+t1.minute-t0.minute
def addtime_mintue(t0,m):
    m=m+t0.minute
    return [t0.hour+m//60,m%60]
def time2datetime(t):
    return datetime.datetime(year=2000,month=1,day=1,hour=t.hour,minute=t.minute,second=t.second)
class klinenm:
    def __init__(self,obj,period=5,bars_len=2):
        self.obj=obj
        self.period=period
        self.type=type#1:按根数算，2.按时间算
        self.trade_time=obj_trade(obj)
        self.bar={}
        self.bars = []
        self.bars_len=bars_len
        self.onbarcall = []
        self.tas = []
        self.day=None
        self.data_tradetime2=None
        self.ondata = self.onbar
    def add_ta(self, ta_arg):
        ta0 = ta_frame(ta_arg)
        self.tas.append(ta0)

    def __calc_ta(self, bar):
        for i in self.tas:
            r = i.onbar(bar)
            bar.update(r)
        return bar
    def addtradetime_second(self,t0, m):
        t1 = t0 + datetime.timedelta(seconds=m)
        t2 = self.getbartimekey(t1)
        check=False
        n=0
        tt=self.getstoptime(t2)
        for i in tt:
            if i[0]<t2.time() and t2.time()<i[1]:
                check=True
                break
            n=n+1
        if check:
            gap=tt[n]
            delta=time2datetime(gap[1])-time2datetime(gap[0])
            t1=t1+delta
        return t1
    def setonbar(self,call):
        self.onbarcall.append(call)
    def dividelist(self,l,n):
        total=0
        remainder=[]
        for i in l:
            mintues=subtime_minute(i[1],i[0])
            total=total+mintues
            r=total%n
            remainder.append(r)
        return remainder
    def onbar(self,t):
        # if t["timekey"]==datetime.datetime(2020,1,3,10,10):
        #     print("1")
        if "obj" in t.keys():
            self.obj=t["obj"]

        # if t["timekey"]==datetime.datetime(2021, 3, 22, 11, 29):
        #     print("0")
        if "uptime" in t.keys():
            # print("kline_k5m", t["timekey"], t["uptime"])
            timekey0=t["uptime"]
            btimekey=t["timekey"]
            timekey=self.getbartimekey(btimekey)
            if self.bars:
                bar0=self.bars[-1]
                if timekey==bar0["timekey"]:
                    if bar0["high"]<t["high"]:
                        bar0["high"]=t["high"]
                        bar0["hightime"] = t["hightime"]
                    elif bar0["low"] > t["low"]:
                        bar0["low"] = t["low"]
                        bar0["lowtime"] = t["lowtime"]
                    bar0["close"]=t["close"]
                    bar0["volume"]=bar0["volume"]+t["volume"]
                    bar0["vwap"]=t["vwap"]
                    bar0["pos"]=t["pos"]
                    bar0["uptime"]=timekey0
                    self.__calc_ta(bar0)
                    self.bar = bar0
                else:
                    bar0={}
                    bar0["timekey"]=timekey
                    bar0["obj"]=self.obj
                    bar0["open"]=t["open"]
                    bar0["high"]=t["high"]
                    bar0["low"]=t["low"]
                    bar0["close"]=t["close"]
                    bar0["volume"]=t["volume"]
                    bar0["vwap"]=t["vwap"]
                    bar0["pos"]=t["pos"]
                    bar0["uptime"]=timekey0
                    bar0["hightime"] = t["hightime"]
                    bar0["lowtime"] = t["lowtime"]
                    bar0["opentime"] = t["opentime"]
                    bar0=self.__calc_ta(bar0)
                    self.bars.append(bar0)
                    if len(self.bars)>self.bars_len:
                        self.bars.pop(0)
                    self.bar=bar0
            else:
                bar0={}
                bar0["timekey"]=timekey
                bar0["obj"]=self.obj
                bar0["open"]=t["open"]
                bar0["high"]=t["high"]
                bar0["low"]=t["low"]
                bar0["close"]=t["close"]
                bar0["volume"]=t["volume"]
                bar0["vwap"]=t["vwap"]
                bar0["pos"]=t["pos"]
                bar0["uptime"]=timekey0
                bar0["hightime"] = t["hightime"]
                bar0["lowtime"] = t["lowtime"]
                bar0["opentime"] = t["opentime"]
                self.__calc_ta(bar0)
                self.bars.append(bar0)
                self.bar=bar0

            if self.isendbar(btimekey,timekey):
                for i in self.onbarcall:
                    i(self.bar)
        else:
            # print("kline_k5m", t["timekey"])
            timekey0 = t["timekey"]
            timekey=self.getbartimekey(timekey0)
            if self.bars:
                bar0=self.bars[-1]
                if timekey==bar0["timekey"]:
                    if bar0["high"]<t["high"]:
                        bar0["high"]=t["high"]
                    elif bar0["low"] > t["low"]:
                        bar0["low"] = t["low"]
                    bar0["close"]=t["close"]
                    bar0["volume"]=bar0["volume"]+t["volume"]
                    bar0=self.__calc_ta(bar0)
                    self.bar = bar0
                else:
                    bar0={}
                    bar0["timekey"]=timekey
                    bar0["obj"]=self.obj
                    bar0["open"]=t["open"]
                    bar0["high"]=t["high"]
                    bar0["low"]=t["low"]
                    bar0["close"]=t["close"]
                    bar0["volume"]=t["volume"]
                    bar0=self.__calc_ta(bar0)
                    self.bars.append(bar0)
                    self.bar=bar0
            else:
                bar0={}
                bar0["timekey"]=timekey
                bar0["obj"]=self.obj
                bar0["open"]=t["open"]
                bar0["high"]=t["high"]
                bar0["low"]=t["low"]
                bar0["close"]=t["close"]
                bar0["volume"]=t["volume"]
                bar0=self.__calc_ta(bar0)
                self.bars.append(bar0)
                self.bar=bar0

            if self.isendbar(timekey0, timekey):
                for i in self.onbarcall:
                    i(self.bar)
        return self.bar
    def isendbar(self,a,barkey=""):
        nextk1m=self.trade_time.get_next_bartimekey(a,"k1m")
        b=self.getbartimekey(nextk1m)
        if barkey=="":
            barkey=self.getbartimekey(a)
            return b>barkey
        else:
            return b > barkey

    def getbartimekey(self, a):
        return self.trade_time.getknm_bartimekey_bytimekey(a,self.period)
    def getbartimekey1(self,a):
        tradetimes=self.trade_time.gettrade_datetime(a)
        n = 0
        for i in tradetimes:
            if i[0] < i[1]:
                test = (a >= i[0]) and (a < i[1])
            else:
                test = (a >= i[0]) or (a < i[1])
            if test:
                break
            else:
                n = n + 1
        deltatime=self.trade_time.get_deltatimes(a)
        delta0=sum(deltatime[:n])
        delta1=(a-tradetimes[n][0]).total_seconds()
        size=int((delta0+delta1)/60/self.period)
        delta=size*self.period*60-delta0
        if delta>=0:
            b = tradetimes[n][0] + datetime.timedelta(seconds=delta)
        else:
            b = tradetimes[n-1][1] + datetime.timedelta(seconds=delta)
        return b
class ckline:
    def __init__(self,obj,size=20,bars_len=2):#,skipgap=False
        self.obj=obj
        self.size=size
        self.trade_time=obj_trade(obj)
        self.bar={}
        self.bars = []
        self.bars_len=bars_len
        self.onbarcall = []
        self.counter=1
        self.ondata = self.ontick

    def checktime(self, a):
        return self.trade_time.istradetime(a)
    def setonbar(self,call):
        self.onbarcall=call
    def endday(self,a):
        t=a.time()
        c=self.getstoptime(a)[-1]
        if c[0]>c[1]:
            return t>c[0] or t<c[1]
        else:
            return t > c[0] and t < c[1]
    def ontick(self,t):
        if "obj" in t.keys():
            self.obj=t["obj"]
        if self.endday(t["timekey"]):
            self.counter = 1
        if t["volume"]!=0:
            timekey0 = t["timekey"]
            if not self.checktime(timekey0):
                return {}
            if self.counter==1 or self.counter>self.size  :#add new
                self.counter=1
                bar0 = {}
                bar0["timekey"] = timekey0
                bar0["obj"] = self.obj
                bar0["open"] = t["LastPrice"]
                bar0["high"] = t["LastPrice"]
                bar0["low"] = t["LastPrice"]
                bar0["close"] = t["LastPrice"]
                bar0["volume"] = t["volume"]
                if "AveragePrice" in t.keys():
                    bar0["vwap"] = t["AveragePrice"]
                else:
                    bar0["vwap"]=0
                bar0["pos"]=t["OpenInterest"]
                bar0["uptime"] = timekey0
                bar0["hightime"] = timekey0
                bar0["lowtime"] = timekey0
                bar0["opentime"] = timekey0
                bar0["seqid"]=self.counter
                self.counter=self.counter+1
                self.bars.append(bar0)
                if len(self.bars)>self.bars_len:
                    self.bars.pop(0)
                self.bar=bar0
            else:#update
                bar=self.bars[-1]
                if bar["high"]<t["LastPrice"]:
                    bar["high"]=t["LastPrice"]
                    bar["hightime"] = timekey0
                elif bar["low"]>t["LastPrice"]:
                    bar["low"]=t["LastPrice"]
                    bar["lowtime"] = timekey0
                bar["close"]=t["LastPrice"]
                bar["volume"]=bar["volume"]+t["volume"]
                if "AveragePrice" in t.keys():
                    bar["vwap"] = t["AveragePrice"]
                else:
                    bar["vwap"] = 0
                bar["pos"]=t["OpenInterest"]
                bar["uptime"]=timekey0
                bar["seqid"]=self.counter
                self.counter=self.counter+1
                if self.counter==self.size and self.onbarcall:#call
                    self.onbarcall(bar,self.bar)
        return self.bar
from jili.price.ta import creat_ta_calcor
class klineset:
    def __init__(self,obj,period=[1,5,15],isnight=True,delta=1,ta_args=[],oncall=None):
        self.bars = {}
        self.tas = {}
        self.period=period
        self.obj=obj
        self.isnight=isnight
        self.delta=delta
        self.ta_args=ta_args
        self.oncall=oncall
        for p in period:
            pk = str(p) + "m"
            if p==1:
                self.bars[pk]=kline1m(obj,isnight)
            else:
                self.bars[pk] = klinenm(obj,period=p,isnight=isnight,delta=delta)
            if ta_args:
                for i in ta_args:
                    self.tas[pk] = []
                    self.tas[pk].append(creat_ta_calcor(i))
        if "1m" in self.bars.keys():
            self.bars["1m"].setonbar(self.onbar)
    def setoncall(self,oncall):
        if self.oncall:
            self.oncall = oncall
    def ontick(self,t):
        if "obj" in t.keys():
            self.obj=t["obj"]
        if "1m" in self.bars.keys():
            self.bars["1m"].ontick(t)
    def onbar(self,i):
        if "obj" in i.keys():
            self.obj=i["obj"]
        set = {}
        set["timekey"] = i["timekey"]
        for k,bar in self.bars.items():
            if k=="1m":
                t = {}
                t["timekey"] = i["timekey"]
                for k, v in i.items():
                    t[k] = v
                if self.tas:
                    for ta0 in self.tas["1m"]:
                        tarst = ta0.onbar(i)
                        for k, v in tarst.items():
                            t[k] = v
                set["1m"] = t
            else:
                t = {}
                b = bar.onbar(i)
                for k1, v1 in b.items():
                    t[k1] = v1
                if self.tas:
                    for ta0 in self.tas[k]:
                        tarst = ta0.onbar(b)
                        for k1, v1 in tarst.items():
                            t[k1] = v1
                set[k] = t
        if self.oncall:
            self.oncall(set)
        return set
class barset_research:
    def __init__(self,obj,extra_periods=[5,15],isnight=True,delta=1,ta_args=[],oncall=None,datatype="df"):
        self.bars = {}
        self.tas = {}
        self.extra_periods=extra_periods
        self.obj=obj
        self.isnight=isnight
        self.delta=delta
        self.ta_args=ta_args
        self.oncall=oncall
        self.datatype=datatype
        self.bars["1d"] = kline1d(obj,isnight)
        for p in extra_periods:
            if p not in [0,1]:
                pk = str(p) + "m"
                self.bars[pk] = klinenm(obj,period=p,isnight=isnight,delta=delta)
                self.tas[pk] = []
                for i in ta_args:
                    self.tas[pk].append(creat_ta_calcor(i))
        self.tas["1m"] = []
        self.tas["1d"] = []
        for i in ta_args:
            self.tas["1m"].append(creat_ta_calcor(i))
            self.tas["1d"].append(creat_ta_calcor(i))
    def gethis1dbar(self,date,num=120):
        self.stratdate=date
        from jili.core import load
        k1d=load(r"F:/qjs/data/rb_master_1dk.pkl")
        from jili.tool.convert import convert_datetime
        date1=convert_datetime(date)
        k1dbars = []
        for i in k1d:
            if i["timekey"]<=date1:
                k1dbars.append(i)
        for b in k1dbars[-num:]:
            for ta0 in self.tas["1d"]:
                tarst = ta0.onbar(b)
    def setoncall(self,oncall):
        if oncall:
            self.oncall = oncall
    def onbar(self,i):
        if "obj" in i.keys():
            self.obj=i["obj"]
        set = {}
        set["1m"]=i

        """
        for k,v in i.items():
            set[k+".1m"]=v
        #set.update(i)
        set["timekey"] = i["timekey"]
        set["obj"]=i["obj"]
        set["uptime"]=i["uptime"]
        set["pos"]=i["pos"]
        set["vwap"]=i["vwap"]
        """
        for ta0 in self.tas["1m"]:
            tarst = ta0.onbar(i)
            for k, v in tarst.items():
                set["1m"][k] = v
        for k,bar in self.bars.items():
            b = bar.onbar(i)
            set[k]=b
            for ta0 in self.tas[k]:
                tarst = ta0.onbar(b)
                for k1, v1 in tarst.items():
                    #key=k1+"."+k
                    key=k1
                    set[k][key] = v1
        if self.datatype!="dict":
            set0={}
            for k,v in set.items():
                if isinstance(v,dict):
                    for k1,v1 in v.items():
                        key=k1+"."+k
                        set0[key]=v1
                else:
                    set0[k]=v
        else:
            set0=set
        if self.oncall:
            self.oncall(set0)
        return set0
def tmp_on(set):
    print("tmp_on -oncall:",set)
def test_klineset():
    rst=[]
    from jili.data.db import getk1mbar_pkl
    k1m=getk1mbar_pkl("rb1801")
    ta_args = [{"cmd": "BBANDS", "out": ["upperband", "middleband", "lowerband"],
                "arg": {"timeperiod": 9, "nbdevup": 3, "nbdevdn": 3, "matype": 0}, "batch": 9}]
    p=[1,3]
    #barset=klineset("rb1801",period=p,ta_args=ta_args,oncall=tmp_on)
    barset = barset_research("rb1801", extra_periods=p, ta_args=ta_args, oncall=tmp_on)
    a=k1m[:27]
    for i in a:
        rst.append(barset.onbar(i))
    return rst
if __name__=="__main__":
    #import pandas as pd
    #a=test_klineset()
    # from jili.core import load
    #
    # t = load(r"J:\tickpkl\a1709\a1709_20160317.pkl")
    # from jili.price import kline
    #
    # k = kline.kline1m("a1709", 100 * 200 * 360)
    # for i in t:
    #     k.ontick(i)
    #
    # import pandas as pd
    # kd = pd.DataFrame(k.bars)
    # t = load(r"J:\tickpkl\a1709\a1709_20160318.pkl")
    # for i in t:
    #     k.ontick(i)
    # kd = pd.DataFrame(k.bars)
    # k30 = kline.klinenm("a1709", 30, 100 * 200 * 360)
    # for i in k.bars:
    #     k30.onbar(i)
    # k3 = kline.klinenm("a1709", 3, 100 * 200 * 360)
    # for i in k.bars:
    #     k3.onbar(i)
    k60 = klinenm("sc2105", 60, 100 * 200 * 360)
    print(k60.getbartimekeys1(datetime.datetime(2021,3,17,13,30)))
    # for i in k.bars:
    #     k60.onbar(i)
    # kd3 = pd.DataFrame(k3.bars)
    # kd30 = pd.DataFrame(k30.bars)
    # kd60 = pd.DataFrame(k60.bars)
